//
//					xagg_font.h
//

#ifndef __XAGG_FONT_H
#define __XAGG_FONT_H

#ifndef XAGG_USE_FREETYPE
#include <agg_font_win32_tt.h>
#else
#include <agg_font_freetype.h>
#endif

namespace xagg
{

	class Font
	{
	public:
		enum TextAlignment
		{
			ALIGN_LEFT = 1,
			ALIGN_RIGHT = 2,
			ALIGN_CENTER = 4,
			ALIGN_TOP = 8,
			ALIGN_BOTTOM = 16
		};

		Font
			(
				const char* fontName,
				double height,
				bool bold = false,
				bool italic = false,
				double angle = 0.0
			) :
				m_textAngle( angle ),
				m_fontHeight( height ),
				m_textHints ( true ),
				m_textAlign( ALIGN_LEFT | ALIGN_BOTTOM ),
#ifdef AGG2D_USE_FREETYPE
				m_fontEngine(),
#else
				m_fontDC(::GetDC(0)),
				m_fontEngine(m_fontDC),
#endif
				m_fontCacheManager(m_fontEngine)
		{

#ifdef XAGG_USE_FREETYPE
			m_fontEngine.load_font(fontName, 0, agg::glyph_ren_outline );
			m_fontEngine.hinting(m_textHints);
			m_fontEngine.height( height );
#else
			m_fontEngine.hinting( m_textHints );

			flipText( true );

			m_fontEngine.create_font(fontName,
				agg::glyph_ren_outline,
				height,
				0.0,
				bold ? 700 : 400,
				italic);
#endif
		}

		void flipText(bool flip)
		{
			m_fontEngine.flip_y(flip);
		}

		double fontHeight() const
		{
			return m_fontHeight;
		}

		void textAlignment( TextAlignment align )
		{
			m_textAlign = align;
		}

		bool textHints() const
		{
			return m_textHints;
		}

		void textHints(bool hints)
		{
			m_textHints = hints;
		}

		double textWidth( const String& str )
		{
			double x = 0;
			double y = 0;
			bool first = true;

			String::const_iterator istr = str.begin();

			while( istr != str.end() )
			{
				const agg::glyph_cache* glyph = m_fontCacheManager.glyph(*istr);
				if(glyph)
				{
					if(!first) m_fontCacheManager.add_kerning(&x, &y);
					x += glyph->advance_x;
					y += glyph->advance_y;
					first = true;
				}
				++istr;
			}
			return x;
		}

		template< typename RendererT >
		void renderText
			(
				RendererT& ren,
				double x, 
				double y, 
				const String& str, 
				bool roundOff = false, 
				double ddx = 0.0, 
				double ddy = 0.0 
			)
		{
			double dx = 0.0;
			double dy = 0.0;

			if( m_textAlign & ALIGN_CENTER )
				dx = - textWidth(str) * 0.5;
			else if( m_textAlign & ALIGN_RIGHT )
				dx = -textWidth(str);

			double asc = fontHeight();
			const agg::glyph_cache* glyph = m_fontCacheManager.glyph('H');
			if( glyph )
			{
				asc = glyph->bounds.y2 - glyph->bounds.y1;
			}

			if( m_textAlign & ALIGN_CENTER )
				dy = -asc * 0.5;
			else if( m_textAlign & ALIGN_TOP )
				dy = -asc;

			if( m_fontEngine.flip_y() )
				dy = -dy;

			agg::trans_affine  mtx;

			double start_x = x + dx;
			double start_y = y + dy;

			if ( roundOff ) {
				start_x = int( start_x );
				start_y = int( start_y );
			}
			start_x += ddx;
			start_y += ddy;

			mtx *= agg::trans_affine_translation( -x, -y );
			mtx *= agg::trans_affine_rotation( m_textAngle );
			mtx *= agg::trans_affine_translation( x, y );

			agg::conv_transform<FontCacheManager::path_adaptor_type> tr( m_fontCacheManager.path_adaptor(), mtx );

			int i;
			for (i = 0; str[i]; i++) {
				glyph = m_fontCacheManager.glyph(str[i]);
				if( glyph ) {
					if(i) 
						m_fontCacheManager.add_kerning(&x, &y);
					m_fontCacheManager.init_embedded_adaptors(glyph, start_x, start_y);

					if( glyph->data_type == agg::glyph_data_outline )
						ren.render( tr );

					start_x += glyph->advance_x;
					start_y += glyph->advance_y;
				}
			}
		}

	private:

#ifdef XAGG_USE_FREETYPE
		typedef agg::font_engine_freetype_int32       FontEngine;
#else
		typedef agg::font_engine_win32_tt_int32       FontEngine;
#endif
		typedef agg::font_cache_manager<FontEngine>   FontCacheManager;

#ifndef XAGG_USE_FREETYPE
		HDC                             m_fontDC;
#endif
		FontEngine                      m_fontEngine;
		FontCacheManager                m_fontCacheManager;

		double m_textAngle;
		double m_fontHeight;
		bool m_textHints;
		unsigned m_textAlign;
	};
}

#endif
